import {CardInfo, CardType, Direction, DirectionMode, GridInfo, GridsLib} from "../../Libs/GridsLib";
import CardLib from "../../Libs/CardLib";
import {getRandomIntInclusive, randByWeight, WeightItem} from "../../Libs/Untils";
import BaseUI from "../../../Core/BaseUI";

const {ccclass, property} = cc._decorator;


@ccclass
class BattleUI extends BaseUI {
    //格子分布父节点
    @property(cc.Node)
    gridNode: cc.Node = null;

    @property(cc.Node)
    bossCounter: cc.Node = null;

    @property(cc.Node)
    coinCounter: cc.Node = null;


    private isMoving = true;
    public gridsLib: GridsLib

    private defaultBossStep:number = 10
    private moveStep:number = 0;
    private coinTotal:number = 0;


    async onShow(data?: any): Promise<void> {
        this.gridsLib = new GridsLib(this.gridNode)
        await this.gridsLib.generateGrids(3, 3);

        this.gridsLib.registerClickEvent(this.clickNode, this)

        await this.gridsLib.setGridsCard([
            <CardInfo>{type: CardType.Monster, id: 9, value: 2},
            <CardInfo>{type: CardType.Health, id: 1, value: 2},
            <CardInfo>{type: CardType.Trap, id: 1, value: 1},
            <CardInfo>{type: CardType.Treasure, id: 1, value: 3},
            <CardInfo>{type: CardType.Hero, id: 2, value: 10, maxValue: 10},
            <CardInfo>{type: CardType.Health, id: 1, value: 3},
            <CardInfo>{type: CardType.Trap, id: 1, value: 1},
            <CardInfo>{type: CardType.Monster, id: 3, value: 1},
            <CardInfo>{type: CardType.Health, id: 1, value: 1},
            <CardInfo>{type: CardType.Trap, id: 1, value: 1},
            <CardInfo>{type: CardType.Monster, id: 3, value: 1},
            <CardInfo>{type: CardType.Health, id: 1, value: 1},
        ]);

        //boss步数初始
        this.setBossStep(this.defaultBossStep)

        //金币数
        this.setCoinCount(0)

        this.isMoving = false;


    }
    onHide(): Promise<void> {
        return
    }


    async clickNode(event: cc.Event) {

        if (this.isMoving) {
            return;
        }

        let targetGrid = this.gridsLib.getGridInfoByNode(event.target);

        if (targetGrid.cardInfo.type == CardType.Hero) {
            return;
        }

        let heroInfo = this.gridsLib.getGridInfoByCardType(CardType.Hero)[0]

        let offset: cc.Vec2 = heroInfo.vec2.sub(targetGrid.vec2);
        let direction: Direction;

        if (offset.x == 0 && offset.y == 1) {
            direction = Direction.Left;
        } else if (offset.x == 0 && offset.y == -1) {
            direction = Direction.Right;
        } else if (offset.x == 1 && offset.y == 0) {
            direction = Direction.UP;
        } else if (offset.x == -1 && offset.y == 0) {
            direction = Direction.Down;
        } else {
            return;
        }


        //移动检测
        if (this.canMove(heroInfo, targetGrid)) {
            //先移动卡牌
            await this.move(direction, heroInfo, targetGrid)
        }

        //触发效果
        await this.triggerEffect(heroInfo, targetGrid)

        this.isMoving = false;
    }

    public isDead(heroInfo: GridInfo, targetGrid: GridInfo): boolean {
        return heroInfo.node.getComponent(CardLib).hp <= targetGrid.cardInfo.value;
    }

    public canMove(heroInfo: GridInfo, targetGrid: GridInfo): boolean {
        switch (targetGrid.cardInfo.type) {
            case CardType.Treasure:
                return false;
            case CardType.Boss:
            case CardType.Monster:
            case CardType.Trap:
                return this.isDead(heroInfo, targetGrid) == false
            default:
                return true;
        }
    }

    public async triggerEffect(heroInfo: GridInfo, targetGrid: GridInfo) {
        switch (targetGrid.cardInfo.type) {
            case CardType.Treasure:

                await this.gridsLib.setCardOnGrid(this.getTreasureRandCardInfo(targetGrid.cardInfo.value), targetGrid)

                break;
            case CardType.Shield:
                heroInfo.node.getComponent(CardLib).addDefenseValue(targetGrid.cardInfo.value);
                break;
            case CardType.Boss:
                this.moveStep = 0; //恢复计数
                this.setBossStep(this.defaultBossStep)
            case CardType.Monster:
            case CardType.Trap:
                if (this.isDead(heroInfo, targetGrid)) {
                    //死亡动画
                    break;
                }

                //扣血
                heroInfo.node.getComponent(CardLib).addHp(-targetGrid.cardInfo.value);
                break;
            case CardType.Health:
                //加血
                heroInfo.node.getComponent(CardLib).addHp(targetGrid.cardInfo.value);
                break;
            case CardType.Coin:
                this.coinTotal += targetGrid.cardInfo.value
                this.setCoinCount(this.coinTotal)
                break;
            case CardType.Skill:
                await this.triggerSkillEffect(targetGrid);
                break;
            default:
                return;
        }
    }

    public async triggerSkillEffect(skillGrid: GridInfo) {
        let heroInfo = this.gridsLib.getGridInfoByCardType(CardType.Hero)[0]

        for( let direction of [Direction.UP,Direction.Down,Direction.Left,Direction.Right]){
            let targetGrid = this.gridsLib.getGridInfoByDirection(heroInfo.index,Number(direction),DirectionMode.Forward)
            if(!targetGrid){
                continue;
            }

            switch (targetGrid.cardInfo.type) {
                case CardType.Shield:
                case CardType.Boss:
                case CardType.Monster:
                case CardType.Trap:
                case CardType.Health:
                    //能扣完
                    if( skillGrid.cardInfo.value >= targetGrid.cardInfo.value ){
                        if(targetGrid.cardInfo.type == CardType.Boss){
                            this.moveStep = 0; //恢复计数
                            this.setBossStep(this.defaultBossStep)
                        }

                        let cardInfo = {type:CardType.Coin,id:this.getCardRandId(CardType.Coin),value:this.getCardRandValue(CardType.Coin)}
                        await this.gridsLib.setCardOnGrid(cardInfo,targetGrid,true);

                    }
                    //扣除卡值
                    else{
                        targetGrid.node.getComponent(CardLib).addValue( -skillGrid.cardInfo.value );
                        targetGrid.cardInfo.value -= skillGrid.cardInfo.value;
                    }
                    break;
                case CardType.Coin:
                case CardType.Skill:
                    targetGrid.node.getComponent(CardLib).addValue( skillGrid.cardInfo.value );
                    targetGrid.cardInfo.value += skillGrid.cardInfo.value;
                    break;
            }

        }
    }


    async move(direction: number, heroGrid: GridInfo, targetGrid: GridInfo) {

        //移动数组 前一个是后一个的移动目标
        let moveList: GridInfo[] = [targetGrid, heroGrid];

        //跟随移动的节点
        //获取 背后的所有节点
        let followGrids = this.gridsLib.getAllGridsInfoByDirection(heroGrid.index, direction, DirectionMode.Behind)

        //没有背后的节点 先找顺时针方向的
        if (followGrids.length == 0) {
            followGrids = this.gridsLib.getAllGridsInfoByDirection(heroGrid.index, direction, DirectionMode.Clockwise)
        }

        //还没有 找逆时针方向的
        if (followGrids.length == 0) {
            followGrids = this.gridsLib.getAllGridsInfoByDirection(heroGrid.index, direction, DirectionMode.AntiClockwise)
        }


        //开始移动 并补卡
        await this.gridsLib.startMove(moveList.concat(followGrids)).then(async (gridInfo) => {
            let cardInfo:CardInfo;
            if(this.moveStep >= 0  ){
                //下一步出boss
                if(this.defaultBossStep - (this.moveStep +1) <= 0){
                    this.moveStep = -1;
                    cardInfo = <CardInfo>{
                        type: CardType.Boss,
                        id: 1,
                        value: this.getCardRandValue(CardType.Boss)
                    }

                    this.setBossStep("-")
                }else{
                    this.moveStep ++;
                    this.setBossStep(this.defaultBossStep - this.moveStep)
                }
            }

            if( !cardInfo){
                cardInfo = this.getMoveRandCardInfo();
            }

            await this.gridsLib.setCardOnGrid(cardInfo, gridInfo)

        });

    }



    //移动补卡
    public getMoveRandCardInfo(){

        //权重数组
        let weightArr = [
            <WeightItem>{id: CardType.Monster, weight: 150},
            <WeightItem>{id: CardType.Trap, weight: 100},
            <WeightItem>{id: CardType.Health, weight: 100},
            <WeightItem>{id: CardType.Coin, weight: 80},
            <WeightItem>{id: CardType.Skill, weight: 100},
            <WeightItem>{id: CardType.Shield, weight: 100},
            <WeightItem>{id: CardType.Treasure, weight: 120},
        ]

        let index = randByWeight(weightArr)

        return <CardInfo>{
            type: weightArr[index].id,
            id: this.getCardRandId(weightArr[index].id),
            value: this.getCardRandValue(weightArr[index].id)
        }
    }

    //宝箱随机卡
    public getTreasureRandCardInfo(value: number): CardInfo {
        //权重数组
        let weightArr = [
            <WeightItem>{id: CardType.Monster, weight: 100},
            <WeightItem>{id: CardType.Trap, weight: 100},
            <WeightItem>{id: CardType.Health, weight: 200},
            <WeightItem>{id: CardType.Coin, weight: 300},
            <WeightItem>{id: CardType.Skill, weight: 200},
            <WeightItem>{id: CardType.Shield, weight: 200},
        ]

        let index = randByWeight(weightArr)

        return <CardInfo>{
            type: weightArr[index].id,
            id: this.getCardRandId(weightArr[index].id),
            value: value
        }
    }


    //获取卡牌随机id
    public getCardRandId(type:CardType ){
        let min:number,max:number;
        switch(type){
            case CardType.Shield:
                min = 1;
                max = 5;
                break;
            case CardType.Monster:
                min = 1;
                max = 9;
                break;
            case CardType.Skill:
                min = 1;
                max = 2;
                break;
            default:
                min = 1;
                max = 1;
        }

        return getRandomIntInclusive(min,max)
    }

    //获取随机卡牌值
    public getCardRandValue( type:CardType  ){
        let min,max:number;
        if(type == CardType.Boss){
             min = 5;
             max = 9;
        }else if(type == CardType.Trap){
            min = 1;
            max = 1;
        }

        else{
            min = 1;
            max = 3
        }

        return getRandomIntInclusive(min,max)
    }


    public setBossStep(n:number|string){
        this.bossCounter.getComponent(cc.Label).string = n.toString()
    }

    public setCoinCount(n:number){
        this.coinCounter.getComponent(cc.Label).string = n.toString()
    }

    // update (dt) {}
}
